package cn.dakaqi.activity.apply.service;

import cn.dakaqi.activity.services.ActivityService;
import cn.dakaqi.entities.Activity;
import cn.dakaqi.entities.ActivityApply;
import cn.dakaqi.entities.Volunteer;
import cn.dakaqi.log.services.LogService;
import cn.dakaqi.member.service.VolunteerService;
import cn.dakaqi.utils.Clock;
import cn.dakaqi.utils.DKQConstant;
import cn.dakaqi.utils.DateUtil;
import cn.dakaqi.utils.ErrorCodeMsg;
import cn.dakaqi.utils.exception.ServiceRuntimeException;
import cn.dakaqi.utils.rongYun.PushActivityMesssage;
import cn.dakaqi.utils.rongYun.PushGroupMesssage;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by chunyang on 2016/4/17.
 */
@Component(value = "activityApplyService")
@Transactional
public class ActivityApplyServiceImpl implements ActivityApplyService
{
    @Autowired
    ActivityApplyDao activityApplyDao;
    @Autowired
    VolunteerService volunteerService;
    @Autowired
    ActivityService activityService;
    @Autowired
    private LogService logService;

    private void saveLog(String message)
    {
        logService.save(300,message);
    }
    @Override
    public void save(String param) throws ServiceRuntimeException
    {
        JSONObject jsonObject = JSON.parseObject(param);
        String memberCode = jsonObject.getString("memberCode");
        String activityCode = jsonObject.getString("activityCode");
        int role = jsonObject.getIntValue("role");

        ActivityApply activityApply = new ActivityApply();
        activityApply.setCreateTime(Clock.DEFAULT.getCurrentDate());

        Volunteer volunteer = volunteerService.findByMemberCode(memberCode);
        if(Volunteer.checkInfo(volunteer) == false)
            throw new ServiceRuntimeException(ErrorCodeMsg.USER_INFO_NOT_FULL);

        activityApply.setVolunteer(volunteer);
        activityApply.setActivity(activityService.findByActivityCode(activityCode));
        activityApply.setRole(role);
        activityApply.setStatus(DKQConstant.APPLY_STATUS_OK);
        this.save(activityApply);
    }

    @Override
    public void save(ActivityApply activityApply) throws ServiceRuntimeException
    {
        //检查当前活动的是否已结束或已被封存
        if(activityApply.getActivity().getStatus() == DKQConstant.PROCEED_END)
            throw new ServiceRuntimeException("活动已结束,不可以报名参加");
        if(activityApply.getActivity().getLocked() == DKQConstant.ACTIVITY_LOCK)
            throw new ServiceRuntimeException("活动已被封存,不可以报名参加");

        //检查活动报名名额是否已满
        if(activityApply.getActivity().getNeeds()>0)
        {
            int applys = this.activityApplyDao.countByActivity(activityApply.getActivity().getId());
            if(applys>= activityApply.getActivity().getNeeds())
                throw new ServiceRuntimeException("名额已满");
        }

        //检查当前用户是否已报过名,并且各个活动不能有时间上的重叠
        Page<ActivityApply> data = this.queryByMemberAndActivityNotEND(activityApply.getVolunteer().getMemberCode(),1);
        if(null != data)
        {
            List<ActivityApply> list = data.getContent();
            if(null != list && list.size()>0)
            {
                for(ActivityApply aa:list)
                {
                    if(DateUtil.isOverLaps(aa.getActivity().getStartTime(),aa.getActivity().getEndTime(),activityApply.getActivity().getStartTime(),activityApply.getActivity().getEndTime(),"yyyy-MM-dd HH:mm") == true)
                    {
                        throw new ServiceRuntimeException("当前活动时间和已报名的活动时间上有重叠,不可以报名");
                    }
                }
            }
        }
        //检查当前用户是否是当前活动的发布者
        if(activityApply.getActivity().getCreateUser().getMemberCode().equals(activityApply.getVolunteer().getMemberCode()))
        {
            activityApply.setRole(DKQConstant.ROLES_CREATEER);
            activityApply.setStatus(DKQConstant.APPLY_STATUS_OK);
        }
        this.activityApplyDao.save(activityApply);
        saveLog("用户【" + activityApply.getVolunteer().getId() + "】报名参加了一个活动【" + activityApply.getActivity().getId() + "】" + activityApply.getActivity().getName());
        joinGroupMesssage(activityApply.getVolunteer().getMemberCode(), activityApply.getVolunteer().getNickName(),activityApply.getActivity().getActivityCode(), activityApply.getActivity().getName());
        //更新活动的报名人数
        Activity activity = activityApply.getActivity();
        activity.setApplys(activity.getApplys()+1);
        this.activityService.update(activity);
    }

    private void joinGroupMesssage(String userId,String userName,String groupCode,String groupName)
    {
        PushGroupMesssage.getInstance().joinGroup("A",userId, userName,groupCode, groupName);
    }
    private void quitGroupMesssage(String userId,String groupCode)
    {
        PushGroupMesssage.getInstance().quitGroup(userId, groupCode);
    }
    @Override
    public void update(ActivityApply activityApply) throws ServiceRuntimeException
    {
        activityApplyDao.save(activityApply);
    }

    @Override
    public void exit(String param) throws ServiceRuntimeException
    {
        JSONObject jsonObject = JSON.parseObject(param);
        String memberCode = jsonObject.getString("memberCode");
        String activityCode = jsonObject.getString("activityCode");

        ActivityApply activityApply = findByVolunteerAndActivity(memberCode,activityCode);
        this.exit(activityApply);
    }

    @Override
    public void exit(ActivityApply activityApply) throws ServiceRuntimeException
    {
        if(null != activityApply)
        {
            //更新活动的报名人数
            Activity activity = activityApply.getActivity();
            int count = activity.getApplys()-1;
            if(count <0)
                count = 0;
            activity.setApplys(count);
            quitGroupMesssage(activityApply.getVolunteer().getMemberCode(),activityApply.getActivity().getActivityCode());
            this.activityService.update(activity);
            saveLog("用户【"+activityApply.getVolunteer().getId()+"】退出活动报名【"+activityApply.getActivity().getId()+"】"+activityApply.getActivity().getName());
            this.activityApplyDao.delete(activityApply);
        }
        else
            throw new ServiceRuntimeException("退出失败");
    }

    @Override
    public void del(Long id) throws ServiceRuntimeException
    {
        ActivityApply activityApply = this.activityApplyDao.findOne(id);
        if(null != activityApply)
        {
            activityApply.setDelStatus(DKQConstant.DEL_YES);
            this.activityApplyDao.save(activityApply);
            saveLog("用户【"+activityApply.getVolunteer().getId()+"】退出活动报名【"+activityApply.getActivity().getId()+"】"+activityApply.getActivity().getName());
            //更新活动的报名人数
            Activity activity = activityApply.getActivity();
            activity.setApplys(activity.getApplys()-1);
            this.activityService.update(activity);
            quitGroupMesssage(activityApply.getVolunteer().getMemberCode(),activityApply.getActivity().getActivityCode());
        }
    }

    @Override
    public void verfier(String memberCode,Long id, int Status) throws ServiceRuntimeException
    {
        ActivityApply activityApply = this.activityApplyDao.findOne(id);
        if(null != activityApply)
        {
            activityApply.setStatus(Status);
            this.activityApplyDao.save(activityApply);
            if(Status == DKQConstant.APPLY_STATUS_OK)
            {
                joinGroupMesssage(activityApply.getVolunteer().getMemberCode(),activityApply.getVolunteer().getNickName(),activityApply.getActivity().getActivityCode(),activityApply.getActivity().getName());
            }
            saveLog("管理员【"+memberCode+"】审核 【"+activityApply.getVolunteer().getId()+"】报名【"+activityApply.getActivity().getId()+"】"+activityApply.getActivity().getName()+",审核结果为"+Status);
        }
    }

    @Override
    public Page<ActivityApply> queryByMember(String memberCode, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);

        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("volunteer.memberCode", new SearchFilter("volunteer.memberCode", SearchFilter.Operator.EQ, memberCode));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        filters.put("activity.delStatus", new SearchFilter("activity.delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        return this.activityApplyDao.findAll(spec, pageRequest);
    }

    @Override
    public Page<ActivityApply> queryByMember(String memberCode, int status, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);

        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("volunteer.memberCode", new SearchFilter("volunteer.memberCode", SearchFilter.Operator.EQ, memberCode));
        filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        return this.activityApplyDao.findAll(spec, pageRequest);
    }


    @Override
    public Page<ActivityApply> queryByActivity(String activityCode, int status, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);

        Map<String,Object> map = new HashMap<String, Object>();
        //map.put("LIKE_NAME",name);
        //Map<String, SearchFilter> filters = SearchFilter.parse(map);

        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("activity.activityCode", new SearchFilter("activity.activityCode", SearchFilter.Operator.EQ, activityCode));
        filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        return this.activityApplyDao.findAll(spec, pageRequest);
    }

    @Override
    public Page<ActivityApply> queryAllByActivity(String activityCode, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("activity.activityCode", new SearchFilter("activity.activityCode", SearchFilter.Operator.EQ, activityCode));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        return this.activityApplyDao.findAll(spec, pageRequest);
    }

    @Override
    public void verfier(String param) throws ServiceRuntimeException
    {
        JSONObject jsonObject = JSON.parseObject(param);
        String memberCode = jsonObject.getString("memberCode");
        Long activityApplyId = jsonObject.getLong("activityApplyId");
        int status = jsonObject.getIntValue("status");
        this.verfier(memberCode,activityApplyId, status);
    }

    @Override
    public void setAdmin(String param) throws ServiceRuntimeException
    {
        JSONObject jsonObject = JSON.parseObject(param);
        Long activityApplyId = jsonObject.getLong("activityApplyId");
        String memberCode = jsonObject.getString("memberCode");
        int role = jsonObject.getIntValue("role");
        this.setAdmin(activityApplyId,role,memberCode);
    }

    @Override
    public void setAdmin(Long id, int role,String memberCode) throws ServiceRuntimeException
    {
        ActivityApply activityApply  = this.activityApplyDao.findOne(id);
        if(null != activityApply)
        {
            activityApply.setRole(role);
            this.activityApplyDao.save(activityApply);

            saveLog("管理员【"+memberCode+"】设置用户【"+activityApply.getVolunteer().getId()+"】为活动【"+activityApply.getActivity().getId()+"】"+activityApply.getActivity().getName() + "的管理员，设置状态为"+ role);

            if (role == DKQConstant.ROLES_ADMIN)
            {
                PushActivityMesssage.getInstance().setActivityMonitor(activityApply.getActivity().getName(),activityApply.getVolunteer().getMemberCode(),activityApply.getActivity().getActivityCode());
            }
        }
    }
    @Override
    public Page<ActivityApply> queryByMemberAndActivityNotEND(String memberCode, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);

        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("volunteer.memberCode", new SearchFilter("volunteer.memberCode", SearchFilter.Operator.EQ, memberCode));
        filters.put("activity.status", new SearchFilter("activity.status", SearchFilter.Operator.LT, DKQConstant.PROCEED_END));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        return this.activityApplyDao.findAll(spec, pageRequest);
    }

    @Override
    public ActivityApply findByVolunteerAndActivity(Volunteer volunteer, Activity activity) throws ServiceRuntimeException
    {
        return findByVolunteerAndActivity(volunteer.getMemberCode(),activity.getActivityCode());
    }

    @Override
    public ActivityApply findByVolunteerAndActivity(String memberCode, String activityCode) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("volunteer.memberCode", new SearchFilter("volunteer.memberCode", SearchFilter.Operator.EQ, memberCode));
        filters.put("activity.activityCode", new SearchFilter("activity.activityCode", SearchFilter.Operator.EQ, activityCode));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        List<ActivityApply> list = this.activityApplyDao.findAll(spec);
        if(null != list && list.size()>0)
            return list.get(0);
        return null;
    }
}
